CMAKE = $(shell which cmake3 || which cmake)
GITREV = $(shell git rev-parse --short HEAD)
SRCPWD = $(shell pwd)

BUILD_DIR_PREFIX = build

# origin checks to see where the value of CC came from.
# If it is still set to the default, then over write it with a new default.
# This must be done for variables like CC for which the Makefile
# assigns a default value. Other variables, like CXX (next line), can use the 
# ?= syntax because Makefile does not assign them a default value. 
ifeq ($(origin CC),default)
CC = gcc
endif
CXX ?= g++

TARGETS := opt dbg vgr gpf

.PHONY: all default clean clean_pin_exec pin_exec $(TARGETS) $(subst %, clean%, $(TARGETS))

default: opt

all: $(TARGETS)

opt: BUILD_TYPE = ScarabOpt
opt: $(BUILD_DIR_PREFIX)/opt/scarab_phony ## Build Scarab with optimization flags

dbg: BUILD_TYPE := Debug
dbg: $(BUILD_DIR_PREFIX)/dbg/scarab_phony ## Build Scarab in debug mode

vgr: BUILD_TYPE := Valgrind
vgr: $(BUILD_DIR_PREFIX)/vgr/scarab_phony ## Build Scarab in Valgrind mode

gpf: BUILD_TYPE := Gprof
gpf: $(BUILD_DIR_PREFIX)/gpf/scarab_phony ## Build Scarab in Gprof mode

pin_exec:
	make SCARAB_DIR=$(SRCPWD) pin_exec --directory pin/pin_exec	 --no-print-directory

clean_pin_exec:
	make --directory pin/pin_exec clean --no-print-directory

clean%: ## Clean a specific build directory
	rm -rf build/$*
	rm -f scarab

clean: clean_pin_exec ## Clean all build directories
	rm -rf build/
	rm -f scarab

gitrev::
	@[ -f $@ ] || touch $@
	@echo '"'$(GITREV)'"' | cmp -s $@ - || echo '"'$(GITREV)'"' > $@

clang-format: ## Run clang-format on the entire repository (not just src/*)
	../bin/run_clang_format_on_all.sh

release: clang-format ## Run clang-format and compile opt, dbg, vgr, and gpf. Should be run to ensure Scarab is ready for release.
	make --no-print-directory clean
	make --no-print-directory -j all
	@echo
	@echo "Ready for release!"

help: ## Print this message
	@echo "Scarab Makefile:"
	@echo
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

help-nocolor: ## Print this message
	@echo "# Scarab Makefile:"
	@echo
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "* **%-30s:**\t\t%s\n", $$1, $$2}'

# Calls the Makefile generated by CMake.
# scarab_phony is a fake file that causes this rule to always run.
# We tried to make this a phony target, but it did not work. We suspect phony
# targets cannot be file paths.
$(BUILD_DIR_PREFIX)/%/scarab_phony: $(BUILD_DIR_PREFIX)/%/Makefile gitrev pin_exec
	@make -j --no-print-directory -C $(dir $@)
	ln -sf $(dir $@)scarab scarab

# Creates the build directory and configures the CMake project.
# .SECONDARY tells Make to not delete the intermediate Makefile created by this rule.
.SECONDARY: $(patsubst %, $(BUILD_DIR_PREFIX)/%/Makefile, $(TARGETS))
$(BUILD_DIR_PREFIX)/%/Makefile:
	mkdir -p $(dir $@)
	echo $(CC)
	echo $(CXX)
	cd $(dir $@); \
	  CC=$(CC)      \
	  CXX=$(CXX)     \
	  $(CMAKE) ../.. -DCMAKE_BUILD_TYPE=$(BUILD_TYPE)
